#include "schema_manager.h"
#include "page.h"
#include "url_schema.h"
#include "pending_schema.h"
#include "invalid_schema.h"
#include "keyword_schema.h"
#include "dict_schema.h"
#include "assert.h"

#include "log.h"

int init_schema_op(schema_op_t* schema_op,
				   schema_operate_fun op_ok,
				   schema_operate_fun op_fail)
{
	if(schema_op == 0)
		assert(false);
	schema_op->op_ok = op_ok;
	schema_op->op_fail = op_fail;
	return 0;
}
int init_schema(schema_t* schema, void* data,schema_operate_fun op_release)
{
	if(schema == 0 )
		assert(false);
	schema->data = data;
	schema->next = 0;
	schema->next_op = true;
	schema->func_release = op_release;
	return 0;
}
void del_schema(schema_t* schema)
{
	assert(schema != 0);
	schema->schema_ops.clear();
	delete schema;
	schema = 0;
}

void add_schema_op(schema_t* schema, schema_op_t* schema_op)
{
	if(schema_op == 0 || schema == 0 
	||(schema_op->op_ok==0 && schema_op->op_fail==0))
		assert(false);
		
	schema->schema_ops.push_back(*schema_op);	
}

table_op_t* creat_table_op(schema_t* schema, eTABLE_OP op)
{
	table_op_t* table_op = new table_op_t;
	table_op->schema = schema;
	table_op->op = op;
	return table_op;
}
void del_table_op(table_op_t* table_op)
{
	delete table_op;
	table_op = 0;
}

void run_schema(schema_t* schema)
{
	assert(schema!=0);
	schema_operate_fun fun = schema->schema_ops[schema->next].op_ok; 
	(fun)(schema);
}

int add_page_to_schema(page_t* page)
{
	//insert_url_to_url_db,delete_url_from_pending_db
	schema_t* schema_myurl = new schema_t;
	url_t* url = create_url(&page->url);
	init_schema(schema_myurl,(void*)(url), release_url);
	
	schema_op_t schema_myurl_op_1;
	init_schema_op(&schema_myurl_op_1,add_to_url_schema, add_to_url_schema);
	add_schema_op(schema_myurl, &schema_myurl_op_1);
	
	schema_op_t schema_myurl_op_2;
	init_schema_op(&schema_myurl_op_2,remove_from_pending_schema, remove_from_pending_schema);
	add_schema_op(schema_myurl, &schema_myurl_op_2);
	
	run_schema(schema_myurl);
	 
	 // insert_keywords_to_keywords_db
	schema_t* schema_keyword = new schema_t;
	init_schema(schema_keyword,(void*)(transfer_keyword_from_page(page)), release_keyword);
	schema_op_t schema_keyword_op_1;
	init_schema_op(&schema_keyword_op_1,add_to_keyword_schema, add_to_keyword_schema);
	add_schema_op(schema_keyword, &schema_keyword_op_1);
	
	schema_op_t schema_keyword_op_2;
	init_schema_op(&schema_keyword_op_2,add_to_dict_schema, add_to_dict_schema);
	add_schema_op(schema_keyword, &schema_keyword_op_2);
	
	run_schema(schema_keyword);
		

	//add_hrefs_to_pending(MYSQL* mysql,list<href_t*>& hrefs)
	list<href_t*>::iterator it = page->hrefs.begin();
	for( ; it != page->hrefs.end(); it++)
	{
		url_t* url = &((*it)->url);
		if( url == 0 || strlen(url->szurl)==0)
			continue;
		schema_t* schema_href = new schema_t;
		url_t* copy_href_url = create_url(url);
		assert(copy_href_url != NULL);
		init_schema(schema_href,(void*)(copy_href_url), release_url);
		
		schema_op_t schema_href_op_1;
		init_schema_op(&schema_href_op_1,exist_in_url_schema, 0);//if fail, will release and stop
		add_schema_op(schema_href, &schema_href_op_1);
	
		schema_op_t schema_href_op_2;
		init_schema_op(&schema_href_op_2,exist_in_pending_schema, 0);
		add_schema_op(schema_href, &schema_href_op_2);
	
		schema_op_t schema_href_op_3;
		init_schema_op(&schema_href_op_3,exist_in_invalid_schema, 0);
		add_schema_op(schema_href, &schema_href_op_3);
		
		schema_op_t schema_href_op_4;
		init_schema_op(&schema_href_op_4,add_to_pending_schema, 0);
		add_schema_op(schema_href, &schema_href_op_4);
		
		run_schema(schema_href);
	}
	return 0;
};

int remove_invalid_url(url_t* url)
{
	//delete_url_from_pending_db, insert into invalid
	schema_t* schema = new schema_t;
	url_t* copy_url = create_url(url);
	init_schema(schema,(void*)(copy_url), release_url);
	
	schema_op_t schema_invalid_op;
	init_schema_op(&schema_invalid_op,add_to_invalid_schema, add_to_invalid_schema);
	add_schema_op(schema, &schema_invalid_op);
	
	schema_op_t schema_pending_op;
	init_schema_op(&schema_pending_op,remove_from_pending_schema, remove_from_pending_schema);
	add_schema_op(schema, &schema_pending_op);
	
	run_schema(schema);
	return 0;
}



int go_next_schema(schema_t* schema, int ret)
{
	assert(schema != NULL);
	schema_operate_fun func_release = schema->func_release;
	schema->next+=1;
	int tmp = schema->schema_ops.size();
	if(schema->next >= schema->schema_ops.size())
	{
		func_release((void*)schema->data);
		del_schema(schema);
	}
	else
	{
		schema_op_t schema_op = schema->schema_ops[schema->next];
		schema_operate_fun func_ok = schema_op.op_ok;
		schema_operate_fun func_fail = schema_op.op_fail;
		if( 0 == ret)
		{
			//ok
			if(func_ok)
			{
				(func_ok)((void*)schema);
			}
			else
			{
				//del 
				func_release((void*)schema->data);
				del_schema(schema);
				
			}
		}
		else
		{
			//ok
			if(func_fail)
			{
				(func_fail)((void*)schema);
			}
			else
			{
				//del 
				func_release((void*)schema->data);
				del_schema(schema);
				
			}
		}
	}
	return 0;
}

